#ifndef YHAIDA_LOGSTREAM_H
#define YHAIDA_LOGSTREAM_H
#include "../base/Utils.h"
#include <iostream>
#include <string>
#include <string.h>
namespace yhaida
{
    class LogStream : Utils::nocapyable
    {
    public:
        typedef Detail::FixedBuffer<Detail::kSmallBuffer> Buffer;
        LogStream() = default;
        ~LogStream() = default;
        LogStream &operator<<(bool flag);
        LogStream &operator<<(short);
        LogStream &operator<<(unsigned short);
        LogStream &operator<<(int);
        LogStream &operator<<(unsigned int);
        LogStream &operator<<(long);
        LogStream &operator<<(unsigned long);
        LogStream &operator<<(long long);
        LogStream &operator<<(unsigned long long);
        LogStream &operator<<(const char *);
        LogStream &operator<<(char);
        LogStream &operator<<(float);
        LogStream &operator<<(double);
        LogStream &operator<<(const std::string &);
        LogStream &operator<<(const void *);
        LogStream &operator<<(const Detail::T &);
        //_buffer里面用memcpy
        void append(const char *buff, int len) { _buffer.push_data(buff, len); }
        void reset() { _buffer.reset(); }

        const Buffer &buffer() const { return _buffer; }

    private:
        void staticCheck();

        template <typename T>
        void formatInt(T);

        Buffer _buffer;

        static const int kMaxNumericSize = 32;
    };

    //格式化输入
    class Fmt : Utils::nocapyable
    {
    public:
        template <typename T>
        Fmt(const char *fmt, T value)
        {
            //判断T是不是算数类型
            static_assert(std::is_arithmetic<T>::value == true);
            _length = snprintf(_data, sizeof(_data) / sizeof(char), fmt, value);
            //判断下有没有fmt消息超过长度
            assert(static_cast<size_t>(_length) < sizeof(_data));
        }
        ~Fmt() = default;
        //第二个const必须加，否则会出现“passing ‘const’ as ‘this’ argument discards qualifiers错误”
        const char *data() const { return _data; }
        int length() const { return _length; }

    private:
        char _data[32];
        int _length;
    };

    inline LogStream &operator<<(LogStream &l, const Fmt &fmt)
    {
        l.append(fmt.data(), fmt.length());
        return l;
    }
}

#endif